﻿using System;
using System.Windows.Controls;
using System.Collections.Generic;
using System.Reflection;
using PSE.Framework.UI.Resources;
using System.Collections;
using Sinacor.Infra.UI.Common;
using Sinacor.Infra.Common;
using System.ComponentModel;
using System.Linq;

namespace Sinacor.Infra.UI.Controls.SmartClient
{
    public class SinacorReport : Control
    {
        #region  Constants
        private const string DEFAULT_REPORT_TITLE_RESOURCEKEY = "Infra.Controls.Label.TituloPadraoRelatorio";

        #endregion
        #region Fields

        private List<SinacorReportFormatObjects> _formatObjects;
        private List<SinacorReportDataObjects> _dataObjects;
        private List<SinacorReportParameterValue> _parametersValues;
        private Dictionary<String, String> _titleSubReports;

        private SinacorWindow _ownerWindow;
        /// <summary>
        /// Indica qu será utilizada uma legenda para os nomes das colunas
        /// </summary>
        private bool _columnMappedChecked;
        #endregion

        #region Constructor

        private SinacorReport()
        {
        }

        /// <summary>
        /// Construtor padrão
        /// </summary>
        public SinacorReport(SinacorWindow ownerWindow)
        {
            if (ownerWindow == null)
                throw new ArgumentNullException("ownerWindow");

            this._ownerWindow = ownerWindow;
            this._formatObjects = new List<SinacorReportFormatObjects>();
            this._dataObjects = new List<SinacorReportDataObjects>();
            this._parametersValues = new List<SinacorReportParameterValue>();
            this._titleSubReports = new Dictionary<String, String>();
        }

        #endregion

        #region SetColumns / AddColumns

        /// <summary>
        /// Define os títulos e o controle de visualização das colunas dos relatórios manuais
        /// </summary>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        public void SetColumns(String columnTitleResourceKey, String propertyName)
        {
            this.AddColumns(String.Empty, true, columnTitleResourceKey, propertyName, 100, AlignmentColumn.LeftAlign, false, null, null);
        }

        /// <summary>
        /// Define os títulos e o controle de visualização das colunas dos relatórios manuais
        /// </summary>
        /// <param name="subReportName">Nome do SubRelatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        public void SetColumns(String subReportName, String columnTitleResourceKey, String propertyName)
        {
            this.AddColumns(subReportName, true, columnTitleResourceKey, propertyName, 100, AlignmentColumn.LeftAlign, false, null, null);
        }

        /// <summary>
        /// Define os títulos e o controle de visualização das colunas dos relatórios manuais
        /// </summary>
        /// <param name="subReportName">Nome do SubRelatório</param>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>        
        public void SetColumns(String subReportName, Boolean displayParameter, String columnTitleResourceKey, String propertyName)
        {
            this.AddColumns(subReportName, displayParameter, columnTitleResourceKey, propertyName, 100, AlignmentColumn.LeftAlign, false, null, null);
        }

        /// <summary>
        /// Define os títulos e o controle de visualização das colunas dos relatórios manuais
        /// </summary>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>        
        public void SetColumns(Boolean displayParameter, String columnTitleResourceKey, String propertyName)
        {
            this.AddColumns(String.Empty, displayParameter, columnTitleResourceKey, propertyName, 100, AlignmentColumn.LeftAlign, false, null, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        public void AddColumns(String columnTitleResourceKey, String propertyName, Int16 widthColumn)
        {
            this.AddColumns(String.Empty, true, columnTitleResourceKey, propertyName, widthColumn, AlignmentColumn.LeftAlign, true, null, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        /// <param name="alignmentColumn">Alinhamento da coluna no relatório</param>        
        public void AddColumns(String columnTitleResourceKey, String propertyName, Int16 widthColumn, AlignmentColumn alignmentColumn)
        {
            this.AddColumns(String.Empty, true, columnTitleResourceKey, propertyName, widthColumn, alignmentColumn, true, null, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>        
        public void AddColumns(Boolean displayParameter, String columnTitleResourceKey, String propertyName, Int16 widthColumn)
        {
            this.AddColumns(String.Empty, displayParameter, columnTitleResourceKey, propertyName, widthColumn, AlignmentColumn.LeftAlign, true, null, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        /// <param name="stringFormat"></param>
        public void AddColumns(Boolean displayParameter, String columnTitleResourceKey, String propertyName, Int16 widthColumn, String stringFormat)
        {
            this.AddColumns(String.Empty, displayParameter, columnTitleResourceKey, propertyName, widthColumn, AlignmentColumn.LeftAlign, true, stringFormat, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        /// <param name="maskedTextProvider"></param>
        public void AddColumns(Boolean displayParameter, String columnTitleResourceKey, String propertyName, Int16 widthColumn, MaskedTextProvider maskedTextProvider)
        {
            this.AddColumns(String.Empty, displayParameter, columnTitleResourceKey, propertyName, widthColumn, AlignmentColumn.LeftAlign, true, null, maskedTextProvider);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>        
        /// <param name="fieldWrap">Indica se a coluna carregará em multiplas linhas caso necessário</param>
        public void AddColumns(String columnTitleResourceKey, String propertyName, Int16 widthColumn, Boolean fieldWrap)
        {
            this.AddColumns(String.Empty, true, columnTitleResourceKey, propertyName, widthColumn, AlignmentColumn.LeftAlign, fieldWrap, null, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>        
        /// <param name="alignmentColumn">Alinhamento da coluna no relatório</param>        
        public void AddColumns(Boolean displayParameter, String columnTitleResourceKey, String propertyName, Int16 widthColumn, AlignmentColumn alignmentColumn)
        {
            this.AddColumns(String.Empty, displayParameter, columnTitleResourceKey, propertyName, widthColumn, alignmentColumn, true, null, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        /// <param name="alignmentColumn">Alinhamento da coluna no relatório</param>        
        /// <param name="fieldWrap">Indica se a coluna carregará em multiplas linhas caso necessário</param>
        public void AddColumns(String columnTitleResourceKey, String propertyName, Int16 widthColumn, AlignmentColumn alignmentColumn, Boolean fieldWrap)
        {
            this.AddColumns(String.Empty, true, columnTitleResourceKey, propertyName, widthColumn, alignmentColumn, fieldWrap, null, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        /// <param name="fieldWrap">Indica se a coluna carregará em multiplas linhas caso necessário</param>
        public void AddColumns(Boolean displayParameter, String columnTitleResourceKey, String propertyName, Int16 widthColumn, Boolean fieldWrap)
        {
            this.AddColumns(String.Empty, displayParameter, columnTitleResourceKey, propertyName, widthColumn, AlignmentColumn.LeftAlign, fieldWrap, null, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        /// <param name="alignmentColumn">Alinhamento da coluna no relatório</param>
        /// <param name="fieldWrap">Indica se a coluna carregará em multiplas linhas caso necessário</param>        
        /// <param name="stringFormat">Formatação da coluna</param>
        public void AddColumns(Boolean displayParameter, String columnTitleResourceKey, String propertyName, Int16 widthColumn, AlignmentColumn alignmentColumn, Boolean fieldWrap, String stringFormat)
        {
            this.AddColumns(String.Empty, displayParameter, columnTitleResourceKey, propertyName, widthColumn, AlignmentColumn.LeftAlign, fieldWrap, stringFormat, null);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        /// <param name="alignmentColumn">Alinhamento da coluna no relatório</param>
        /// <param name="fieldWrap">Indica se a coluna carregará em multiplas linhas caso necessário</param>        
        /// <param name="maskedTextProvider">Formatação do coluna</param>
        public void AddColumns(Boolean displayParameter, String columnTitleResourceKey, String propertyName, Int16 widthColumn, AlignmentColumn alignmentColumn, Boolean fieldWrap, MaskedTextProvider maskedTextProvider)
        {
            this.AddColumns(String.Empty, displayParameter, columnTitleResourceKey, propertyName, widthColumn, AlignmentColumn.LeftAlign, fieldWrap, null, maskedTextProvider);
        }

        /// <summary>
        /// Define a formatação e o controle de visualização das colunas dos relatórios dinâmicos
        /// </summary>
        /// <param name="subReportName">Nome do SubRelatório</param>
        /// <param name="displayParameter">Disponibiliza para o usuário o controle de visualização da coluna no relatório</param>
        /// <param name="columnTitleResourceKey">ResourceKey cadastrada referente ao título da coluna no relatório</param>
        /// <param name="propertyName">Nome da propriedade da classe que representa os dados na coluna do relatório</param>
        /// <param name="widthColumn">Comprimento em Pixel do objeto no relatório</param>
        /// <param name="alignmentColumn">Alinhamento da coluna no relatório</param>
        /// <param name="fieldWrap">Indica se a coluna carregará em multiplas linhas caso necessário</param>        
        /// <param name="stringFormat">Formatação da coluna</param>
        /// <param name="maskedTextProvider">Formatação da coluna</param>
        private void AddColumns(String subReportName, Boolean displayParameter, String columnTitleResourceKey, String propertyName, Int16 widthColumn, AlignmentColumn alignmentColumn, Boolean fieldWrap, String stringFormat, MaskedTextProvider maskedTextProvider)
        {
            if (String.IsNullOrEmpty(propertyName))
                throw new ArgumentNullException("propertyName");

            this._formatObjects.Add(
                new SinacorReportFormatObjects()
                    {
                        SubReportName = subReportName,
                        TitleColumn = (string)ResourceProviderManager.GetResourceProvider().TryGetResource(columnTitleResourceKey),
                        PropertyName = propertyName,
                        WidthColumn = widthColumn,
                        AlignmentColumn = alignmentColumn,
                        FieldWrap = fieldWrap,
                        DisplayParameter = displayParameter,
                        IsVisible = true,
                        StringFormat = stringFormat,
                        MaskedTextProvider = maskedTextProvider
                    });
        }

        #endregion

        #region SetDataObjects

        /// <summary>
        /// Define os dados do relatório
        /// </summary>
        /// <param name="reportTable">Nome da tabela de dados do relatório</param>
        /// <param name="data">Dados que serão carregados na tabela de dados do relatório</param>
        public void SetDataObjects(String reportTable, Object data)
        {
            this.SetDataObjects(String.Empty, reportTable, data);
        }

        /// <summary>
        /// Define os dados do relatório
        /// </summary>
        /// <param name="subReportName">Nome do SubRelatório</param>
        /// <param name="reportTable">Nome da tabela de dados do relatório</param>
        /// <param name="data">Dados que serão carregados na tabela de dados do relatório</param>
        public void SetDataObjects(String subReportName, String reportTable, Object data)
        {
            this._dataObjects.Add(new SinacorReportDataObjects() { SubReportName = subReportName, ReportTable = reportTable, Data = data });
        }

        #endregion

        #region SetSubReportTitle

        /// <summary>
        /// Define o título do relatório, que será usado para diferenciar campos na tela de Campos Opcionais
        /// </summary>
        /// <param name="subReportName">Nome do SubRelatório</param>
        /// <param name="subReportTitleResourceKey">Título do SubRelatório, deve ser uma ResourceKey</param>
        public void SetSubReportTitle(String subReportName, String subReportTitleResourceKey)
        {
            if (String.IsNullOrEmpty(subReportTitleResourceKey))
                throw new ArgumentNullException("titleSubReport");

            this._titleSubReports.Add
                (
                    subReportName,
                    subReportTitleResourceKey
                );
        }

        #endregion

        #region SetParameterValue

        /// <summary>
        /// Atribui valores para os parâmetros de relatório criados nos relatórios manuais
        /// </summary>
        /// <param name="parameterName">Nome do parâmetro no relatório</param>
        /// <param name="parameterValue">Valor do parâmetro no relatório</param>
        public void SetParameterValue(String parameterName, Object parameterValue)
        {
            this.SetParameterValue(String.Empty, parameterName, parameterValue);
        }

        /// <summary>
        /// Atribui valores para os parâmetros de relatório criados nos relatórios manuais
        /// </summary>
        /// <param name="subReportName">Nome do SubRelatório</param>
        /// <param name="parameterName">Nome do parâmetro no relatório</param>
        /// <param name="parameterValue">Valor do parâmetro no relatório</param>
        public void SetParameterValue(String subReportName, String parameterName, Object parameterValue)
        {
            this._parametersValues.Add
                (
                    new SinacorReportParameterValue()
                    {
                        SubReportName = subReportName,
                        ParameterName = parameterName,
                        ParameterValue = parameterValue
                    }
                );
        }

        #endregion

        #region FormatValue

        private String FormatValue(Object value, MaskedTextProvider maskedTextProvider)
        {
            maskedTextProvider.Set(value.ToString());
            return maskedTextProvider.ToString();
        }

        private String FormatValue(String type, Object value, String stringFormat)
        {
            String result = value.ToString();

            if (type.Contains("System.Int16"))
                result = Int16.Parse(result).ToString(stringFormat);
            else if (type.Contains("System.Int32"))
                result = Int32.Parse(result).ToString(stringFormat);
            else if (type.Contains("System.Int64"))
                result = Int64.Parse(result).ToString(stringFormat);
            else if (type.Contains("System.Decimal"))
                result = Decimal.Parse(result).ToString(stringFormat);
            else if (type.Contains("System.Double"))
                result = Double.Parse(result).ToString(stringFormat);
            else if (type.Contains("System.DateTime"))
                result = DateTime.Parse(result).ToString(stringFormat);

            return result;
        }

        #endregion

        #region FormatProperties

        private Object FormatProperties(List<PropertyValueType> propertiesInfo, String stringFormat, String maskedText)
        {
            Object propertyValue = null;
            String format = stringFormat;

            if (propertiesInfo.Count > 0)
            {
                if (propertiesInfo.Count > 1)
                {
                    if (String.IsNullOrEmpty(stringFormat))
                    {
                        for (int i = 0; i < propertiesInfo.Count; i++)
                        {
                            if (i > 0)
                                format += " ";

                            format += "{" + i + "}";
                        }
                    }

                    Object[] propertiesArray = propertiesInfo.ConvertAll<Object>(
                                                    delegate(PropertyValueType value)
                                                    {
                                                        return GetPropertyValue(value.PropertyValue);
                                                    }
                                               ).ToArray();

                    propertyValue = String.Format(format, propertiesArray);

                    if (!String.IsNullOrEmpty(maskedText))
                    {
                        MaskedTextProvider masked = new MaskedTextProvider(maskedText);
                        masked.Set(propertyValue.ToString());
                        propertyValue = masked.ToString();
                    }
                }
                else
                {
                    // Sem formatação
                    if (String.IsNullOrEmpty(stringFormat) && String.IsNullOrEmpty(maskedText))
                        propertyValue = GetPropertyValue(propertiesInfo[0].PropertyValue);
                    // Formatação com ReportStringFormat
                    else if (!String.IsNullOrEmpty(stringFormat) && String.IsNullOrEmpty(maskedText))
                        propertyValue = this.FormatValue(propertiesInfo[0].PropertyType.FullName, GetPropertyValue(propertiesInfo[0].PropertyValue), stringFormat);
                    // Formatação com ReportMaskedText
                    else if (String.IsNullOrEmpty(stringFormat) && !String.IsNullOrEmpty(maskedText))
                    {
                        MaskedTextProvider masked = new MaskedTextProvider(maskedText);
                        masked.Set(GetPropertyValue(propertiesInfo[0].PropertyValue).ToString());
                        propertyValue = masked.ToString();
                    }
                }
            }

            return propertyValue;
        }

        #endregion

        #region GetPropertyValue

        private Object GetPropertyValue(Object value)
        {
            Object propertyValue = null;

            //Boleano - Sim ou Não
            if (value is Boolean ||
                value is Boolean?)
            {
                if (value != null)
                {
                    if (Convert.ToBoolean(value))
                        propertyValue = (String)ResourceProviderManager.GetResourceProvider().TryGetResource("Infra.Common.Label.Sim");
                    else
                        propertyValue = (String)ResourceProviderManager.GetResourceProvider().TryGetResource("Infra.Common.Label.Nao");
                }
            }
            //EnumWrapper - Retorna Descrição do Enum
            else if (value is IEnumWrapper)
                propertyValue = ((IEnumWrapper)value).Text;
            //Qualquer outro Type - Retorna o mesmo Type
            else
                propertyValue = value;

            return propertyValue;
        }

        #endregion

        #region Show

        private bool PreReportShow(ref String reportTitleResourceKey)
        {
            if (String.IsNullOrEmpty(reportTitleResourceKey))
                reportTitleResourceKey = DEFAULT_REPORT_TITLE_RESOURCEKEY;

            SinacorReportParameterWindow sinacorReportParameterWindow;
            // Abre a tela para o usuário informar quais campos irão ser mostrados no relatório
            sinacorReportParameterWindow = new SinacorReportParameterWindow(this._formatObjects, false, reportTitleResourceKey);
            sinacorReportParameterWindow.Owner = this._ownerWindow;
            sinacorReportParameterWindow.ShowDialog();
            if (sinacorReportParameterWindow.Canceled)
                return false;

            this._columnMappedChecked = sinacorReportParameterWindow.ColumnMappedChecked;
            // Captura somente as colunas que serão visíveis no relatório
            this._formatObjects = sinacorReportParameterWindow.FormatObjects.FindAll(x => x.IsVisible);

            //caso mais de 1 item esteja marcado como visible, abrir a janela de ordenacao
            if (this._formatObjects.Count(x => x.IsVisible) > 1)
            {
                SinacorReportFieldOrderWindow fieldOrderWindow = new SinacorReportFieldOrderWindow(this._formatObjects, reportTitleResourceKey);
                fieldOrderWindow.Owner = this._ownerWindow;
                fieldOrderWindow.ShowDialog();
                if (fieldOrderWindow.Canceled)
                    return false;

                this._formatObjects = fieldOrderWindow.OrderFormatObjects.ToList();
            }

            return true;
        }



        /// <summary>
        /// Monta relatório de acordo com os dados de uma lista genérica
        /// </summary>
        /// <typeparam name="T">Tipo genérico</typeparam>
        /// <param name="data">Lista contendo os dados que serão visualizados no relatório</param>
        /// <param name="reportTitleResourceKey">Título do relatório, deve sempre ser uma ResourceKey</param>
        public void Show<T>(System.Collections.ObjectModel.ObservableCollection<T> data, String reportTitleResourceKey)
        {
            //se em algum ponto do processamento pre-abertura da janela de relatorio houve um cancelamento
            if (!PreReportShow(ref reportTitleResourceKey))
                return;

            // Instancia a carrega a classe de dados do relatório
            List<SinacorReportDataSource> sinacorReportDataSource = new List<SinacorReportDataSource>();
            Int16 i = 1;
            foreach (Object obj in data)
            {
                SinacorReportDataSource ds = new SinacorReportDataSource();

                foreach (SinacorReportFormatObjects item in this._formatObjects)
                {
                    PropertyInfo pi = obj.GetType().GetProperty(item.PropertyName);

                    Object valorCampo = pi.GetValue(obj, null);
                    if (valorCampo == null)
                        ds.GetType().GetProperty("Campo" + i.ToString()).SetValue(ds, null, null);
                    else
                    {
                        if (!String.IsNullOrEmpty(item.StringFormat))
                            ds.GetType().GetProperty("Campo" + i.ToString()).SetValue(ds, this.FormatValue(pi.PropertyType.FullName, valorCampo, item.StringFormat), null);
                        else if (item.MaskedTextProvider != null)
                            ds.GetType().GetProperty("Campo" + i.ToString()).SetValue(ds, this.FormatValue(valorCampo, item.MaskedTextProvider), null);
                        else
                            ds.GetType().GetProperty("Campo" + i.ToString()).SetValue(ds, valorCampo.ToString(), null);
                    }

                    i++;
                }
                sinacorReportDataSource.Add(ds);
                i = 1;
            }

            // Abre a tela de relatório            
            SinacorReportWindow reportWindow = new SinacorReportWindow(sinacorReportDataSource, this._formatObjects, "Infra.Report.Generic", this._columnMappedChecked, reportTitleResourceKey);
            reportWindow.Owner = this._ownerWindow;
            reportWindow.ShowDialog();
        }



        /// <summary>
        /// Monta relatório em função dos dados de uma DataGrid
        /// </summary>
        /// <param name="itemsSource">Dados do relatório</param>
        /// <param name="columns">Colunas do relatório</param>
        /// <param name="reportTitleResourceKey">Título do relatório, deve sempre ser uma ResourceKey</param>
        public void Show(IEnumerable itemsSource, IEnumerable<Column> columns, String reportTitleResourceKey)
        {
            foreach (Column column in columns)
            {
                if (column.Visible)
                {
                    AlignmentColumn alignmentColumn = (AlignmentColumn)column.HorizontalCellAlignment + 1;
                    this.AddColumns("", true, column.Title.ToString(), column.Name, (Int16)column.Width, alignmentColumn, true, null, null);
                }
            }

            //se em algum ponto do processamento pre-abertura da janela de relatorio houve um cancelamento
            if (!PreReportShow(ref reportTitleResourceKey))
                return;


            List<SinacorReportDataSource> sinacorReportDataSource = new List<SinacorReportDataSource>();

            foreach (Object obj in itemsSource)
            {
                SinacorReportDataSource ds = new SinacorReportDataSource();

                foreach (Column column in columns)
                {
                    if (column.Visible)
                    {
                        SinacorReportFormatObjects item = this._formatObjects.Find(x => x.PropertyName.Equals(column.Name));
                        if (item != null)
                        {
                            if (item.IsVisible)
                            {
                                List<String> displayMembers = column.GetExcelProperties();

                                if (displayMembers.Count > 0)
                                {
                                    //Busca os PropertiesInfo de todos os membros de exibição
                                    List<PropertyValueType> propertiesInfo = obj.GetPropertyInfo(displayMembers);

                                    if (propertiesInfo.Count > 0)
                                    {
                                        //Formata valores dos membros a serem exibidos
                                        Object valorCampo = this.FormatProperties(propertiesInfo, column.ReportStringFormat, column.ReportMaskedText);

                                        if (valorCampo != null)
                                        {
                                            int index = this._formatObjects.IndexOf(item) + 1;
                                            ds.GetType().GetProperty("Campo" + index.ToString()).SetValue(ds, valorCampo.ToString(), null);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                sinacorReportDataSource.Add(ds);
            }

            // Abre a tela de relatório
            SinacorReportWindow reportWindow = new SinacorReportWindow(sinacorReportDataSource, this._formatObjects, "Infra.Report.Generic", this._columnMappedChecked, reportTitleResourceKey);
            reportWindow.Owner = this._ownerWindow;
            reportWindow.ShowDialog();
        }
     

        /// <summary>
        /// Carrega um relatório montado manualmente
        /// </summary>
        /// <param name="reportName">Nome do arquivo de relatório sem a extenção</param>
        /// <param name="reportTitleResourceKey">Título do relatório, deve sempre ser uma ResourceKey</param>
        public void Show(String reportName, String reportTitleResourceKey)
        {
            if (String.IsNullOrEmpty(reportTitleResourceKey))
                reportTitleResourceKey = DEFAULT_REPORT_TITLE_RESOURCEKEY;

            // Abre a tela para o usuário informar quais campos irão ser mostrados no relatório
            SinacorReportParameterWindow sinacorReportParameterWindow = new SinacorReportParameterWindow(this._formatObjects, this._titleSubReports, reportTitleResourceKey);
            sinacorReportParameterWindow.Owner = this._ownerWindow;
            sinacorReportParameterWindow.ShowDialog();
            if (sinacorReportParameterWindow.Canceled)
                return;

            // Abre a tela de relatório
            SinacorReportWindow reportWindow = new SinacorReportWindow(this._dataObjects, this._formatObjects, this._parametersValues, reportName, reportTitleResourceKey);
            reportWindow.Owner = this._ownerWindow;
            reportWindow.ShowDialog();
        }

        #endregion
    }
}
